﻿// basic.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "main.h"
#include "browser/multi_browser_manager.h"
#include "manager/cef_manager.h"

#pragma comment(lib, "dbghelp.lib")

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	std::wstring sCefDirName = L"cef";
#if defined(_M_X64) || defined(__x86_64__)
	sCefDirName += L"_x64";
#else
	sCefDirName += L"_x86";
#endif

#ifdef _DEBUG
	//sCefDirName += L"d";
#endif

	std::wstring sDllPath = nbase::win32::GetCurrentModuleDirectory() + sCefDirName;
	cef::CefManager::GetInstance()->AddCefDllToPath(sDllPath);

	_wsetlocale(LC_ALL, L"chs");

#ifdef _DEBUG
	AllocConsole();
	FILE* fp = NULL;
	freopen_s(&fp, "CONOUT$", "w+t", stdout);
	wprintf_s(L"Command:\n%s\n\n", lpCmdLine);
#endif

	/*HRESULT hr = ::OleInitialize(NULL);			//这段代码会引起libcef.dll中断崩溃
	if (FAILED(hr))
		return 0;*/

//#if defined(ARCH_CPU_32_BITS)
//	int exit_code;
//	// Run the main thread on 32-bit Windows using a fiber with the preferred 4MiB
//	// stack size. This function must be called at the top of the executable entry
//	// point function (`main()` or `wWinMain()`). It is used in combination with
//	// the initial stack size of 0.5MiB configured via the `/STACK:0x80000` linker
//	// flag on executable targets. This saves significant memory on threads (like
//	// those in the Windows thread pool, and others) whose stack size can only be
//	// controlled via the linker flag.
//	exit_code = CefRunWinMainWithPreferredStackSize(wWinMain, hInstance,
//		lpCmdLine, nCmdShow);
//	if (exit_code >= 0) {
//		// The fiber has completed so return here.
//		return exit_code;
//	}
//
//#endif

	// 初始化 CEF
	CefSettings settings;
	if (!cef::CefManager::GetInstance()->Initialize(nbase::win32::GetCurrentModuleDirectory() + L"cef_temp\\"))
	{
		return 0;
	}

	// 创建主线程
	MainThread thread;

	// 执行主线程循环
	thread.RunOnCurrentThreadWithLoop(nbase::MessageLoop::kUIMessageLoop);

    // 清理 CEF
	cef::CefManager::GetInstance()->UnInitialize();

	//::OleUninitialize();

	return 0;
}

void MainThread::Init()
{
	nbase::ThreadManager::RegisterThread(kThreadUI);

	std::wstring sAppDir = nbase::win32::GetCurrentModuleDirectory();
#ifdef _DEBUG
	ui::GlobalManager::Startup(sAppDir + L"\\resources\\", ui::CreateControlCallback(), false, L"themes", L"lang\\zh_CN", L"public\\global.xml");
#else
	ui::GlobalManager::OpenResZip(sAppDir + L"\\resources\\themes\\themes.zip", "");
	ui::GlobalManager::Startup(L"", ui::CreateControlCallback(), false, L"", L"lang\\zh_CN", L"public\\global.xml");
#endif // DEBUG

	nbase::TimeDelta time_delta = nbase::TimeDelta::FromMicroseconds(nbase::Time::Now().ToInternalValue());
	std::string timeStamp = nbase::StringPrintf("%I64u", time_delta.ToMilliseconds());
	MultiBrowserManager::GetInstance()->CreateBorwserBox(NULL, timeStamp, L"");
}

void MainThread::Cleanup()
{
	ui::GlobalManager::Shutdown();
	SetThreadWasQuitProperly(true);
	nbase::ThreadManager::UnregisterThread();
}
